/**
 * Project Name:AccessTokenService.java
 * File Name:AccessTokenService.java
 * Date: 2018/8/28 上午9:50
 * Copyright (c) 2018, zhang.xiangyu@foxmail.com All Rights Reserved.
*/
package com.meatball.api.login.service;

import com.alibaba.fastjson.JSON;
import com.meatball.api.login.params.AccessTokenParams;
import com.meatball.api.login.params.VerifyAccessTokenParams;
import com.meatball.base.system.user.dao.SysUserMapper;
import com.meatball.base.system.user.model.SysUser;
import com.meatball.component.TokenComponent;
import com.meatball.constant.MeatballConst;
import com.meatball.exception.SignatureExpiredException;
import com.meatball.utils.MD5Util;
import com.meatball.vo.TokenResultMsg;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Title: AccessTokenService.java
 * @Description: todo(token相关验证)
 * @Author 張翔宇
 * @Date 2018/8/28 上午9:50
 * @Version V1.0
 */
@Log4j2
@Service
public class AccessTokenService {
    @Resource
    private TokenComponent tokenComponent;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * @Title: getAccessToken
     * @Description: todo(获取token)
     * @Params: [params]
     * @Return: com.meatball.vo.TokenResultMsg    返回类型
     * @Author: 張翔宇
     * @Date: 2018/9/3 下午5:22
     */
    public TokenResultMsg getAccessToken(AccessTokenParams params) throws Exception {
        // 验证签名是否一致，如果一致则返回token
        String token;
        if(this.verifySign(params.getAppId(), params.getTimestamp(), params.getSign())) {
            token = tokenComponent.createJWT(params.getAppId(), stringRedisTemplate.opsForValue().get(params.getAppId()));
        } else {
            return new TokenResultMsg(MeatballConst.ResultCode.SIGNATURE_VERIFICATION_ERROR.CODE,
                    MeatballConst.ResultCode.SIGNATURE_VERIFICATION_ERROR.MESSAGE);
        }
        return  new TokenResultMsg(MeatballConst.ResultCode.SUCCESS.CODE,
                MeatballConst.ResultCode.SUCCESS.MESSAGE, token);
    }

    /**
     * @Title: verifyAccessToken
     * @Description: todo(验证token是否有效)
     * @Params: [record]
     * @Return: com.meatball.vo.TokenResultMsg    返回类型
     * @Author: 張翔宇
     * @Date: 2018/9/3 下午5:22
     */
    public TokenResultMsg verifyAccessToken(VerifyAccessTokenParams record) throws Exception {
        if(this.verifySign(record.getAppId(), record.getTimestamp(), record.getSign())) {
            return  tokenComponent.parseJWT(record.getAccess_token(), stringRedisTemplate.opsForValue().get(record.getAppId()));
        } else {
            return new TokenResultMsg(MeatballConst.ResultCode.SIGNATURE_VERIFICATION_ERROR.CODE,
                    MeatballConst.ResultCode.SIGNATURE_VERIFICATION_ERROR.MESSAGE);
        }
    }

    /**
     * @Title: verifySign
     * @Description: todo(验证sign是否合法)
     * @Params: [appId, timestamp, sign]
     * @Return: boolean    返回类型
     * @Author: 張翔宇
     * @Date: 2018/9/3 下午5:22
     */
    private boolean verifySign(String appId, String timestamp, String sign) throws Exception {
        // 验证签名是否过期
        if((System.currentTimeMillis() - Long.valueOf(timestamp)) / (MeatballConst.ONE_THOUSAND) > MeatballConst.ONE) {
            throw new SignatureExpiredException();
        }
        String appsecret = ""; boolean result = false;
        if(!stringRedisTemplate.hasKey(appId)) {
            SysUser sysUser = sysUserMapper.selectByAppId(appId);
            stringRedisTemplate.opsForValue().append(sysUser.getAppid(), sysUser.getAppsecret());
        } else {
            appsecret = stringRedisTemplate.opsForValue().get(appId);
        }
        Map<String, String> map = new HashMap<>(MeatballConst.THREE);
        map.put(MeatballConst.APPID, appId);
        map.put(MeatballConst.APPSECRET, appsecret);
        map.put(MeatballConst.TIMESTAMP, timestamp);
        String sign_ = MD5Util.MD5Encode(JSON.toJSONString(map));
        if(sign.equals(sign_)) {
            result = true;
        }
        return result;
    }

}
